package processor

import (
	"encoding/json"
	"fmt"
	"net"

	"github.com/clebeg/gochat/protocol"
	"github.com/clebeg/gochat/server/manager"
	"github.com/clebeg/gochat/server/model"
	"github.com/clebeg/gochat/utils"
)

// 根据用户信息和链接器处理用户请求
type UserProcessor struct {
	Conn net.Conn
}

func notifyAllOnlineUsers(userProfile protocol.UserProfile, isOnline bool) {
	for un, ui := range manager.UserMgr.OnlineUsers {
		if un == userProfile.Username {
			continue
		}
		userProcessor := UserProcessor{
			Conn: ui.Conn,
		}
		if isOnline {
			userProcessor.notifyUserLoginProcess(userProfile)
		} else {
			userProcessor.notifyUserLogoutProcess(userProfile)
		}
	}
}

// 通知客户端某个用户登出
func (u *UserProcessor) notifyUserLogoutProcess(userProfile protocol.UserProfile) {
	respMsg := protocol.NotifyLogoutMsgResp{
		ErrorCode:  protocol.Success,
		LogoutUser: userProfile,
	}

	jsonBytes, err := json.Marshal(respMsg)

	if err != nil {
		fmt.Printf("notify logout json.Marshal(respMsg) err, err msg=%v\n", err)
	}
	transfer := utils.Transfer{
		Conn: u.Conn,
	}
	err = transfer.SendMsg(jsonBytes, protocol.NotifyLogoutMsgType)

	if err != nil {
		fmt.Printf("transfer.SendMsg(jsonBytes, protocol.NotifyLogoutMsgType) err, err msg=%v\n", err)
	}
}

// 通知客户端某个用户登录
func (u *UserProcessor) notifyUserLoginProcess(userProfile protocol.UserProfile) {
	respMsg := protocol.NotifyLoginMsgResp{
		ErrorCode:  protocol.Success,
		OnlineUser: userProfile,
	}

	jsonBytes, err := json.Marshal(respMsg)

	if err != nil {
		fmt.Printf("notify login json.Marshal(respMsg) err, err msg=%v\n", err)
	}
	transfer := utils.Transfer{
		Conn: u.Conn,
	}
	err = transfer.SendMsg(jsonBytes, protocol.NotifyLoginMsgType)

	if err != nil {
		fmt.Printf("transfer.SendMsg(jsonBytes, protocol.LoginMsgType) err, err msg=%v\n", err)
	}
}

// 获取登录之后的消息返回类型
func getLoginMsgResp(username int, password int) (respMsg protocol.LoginMsgResp) {
	respMsg = protocol.LoginMsgResp{}
	ok := model.OneUserModel.CheckUserLogin(username)
	if ok {
		respMsg.ErrorCode = protocol.UserAlreadyLogin
		respMsg.ErrorMsg = "用户ID已在其他客户端登录！"
		return
	}

	ok, err := model.OneUserModel.CheckUserExist(username)

	if !ok {
		respMsg.ErrorCode = protocol.UserNotExist
		respMsg.ErrorMsg = "用户ID未被注册，请确认后重新登录！"
		return
	}

	if err != nil {
		respMsg.ErrorCode = protocol.UnkownError
		respMsg.ErrorMsg = err.Error()
		return
	}

	up, err := model.OneUserModel.GetUserByName(username)

	if err != nil {
		respMsg.ErrorCode = protocol.UnkownError
		respMsg.ErrorMsg = err.Error()
		return
	}

	if up.Password != password {
		respMsg.ErrorCode = protocol.PasswordError
		respMsg.ErrorMsg = "密码输入有误，请核对后重新登录！"
	} else {
		respMsg.ErrorCode = protocol.Success
		respMsg.ErrorMsg = "登录成功！"
	}
	return
}

// 处理用户登录请求
func (u *UserProcessor) UserLoginProcess(username int, password int) {
	respMsg := getLoginMsgResp(username, password)

	// 将其他在线的用户加入到消息中
	respMsg.OnlineUsers = make([]protocol.UserProfile, 0)
	for un, ui := range manager.UserMgr.OnlineUsers {
		if un == username {
			continue
		}
		respMsg.OnlineUsers = append(respMsg.OnlineUsers, ui.UserProfile)
	}

	// 返回当前登录成功的用户ID
	respMsg.LoginUsername = username

	jsonBytes, err := json.Marshal(respMsg)

	if err != nil {
		fmt.Printf("login json.Marshal(respMsg) err, err msg=%v\n", err)
	}
	transfer := utils.Transfer{
		Conn: u.Conn,
	}
	err = transfer.SendMsg(jsonBytes, protocol.LoginMsgType)

	if err != nil {
		fmt.Printf("transfer.SendMsg(jsonBytes, protocol.LoginMsgType) err, err msg=%v\n", err)
	}
	// 如果登录成功 且 成功通知到客户端
	if err == nil && respMsg.ErrorCode == protocol.Success {
		userProfile := protocol.UserProfile{
			Username: username,
			Password: password,
		}
		manager.UserMgr.AddOnlineUser(userProfile, u.Conn)
		// 登录成功后，需要通知其他账号我已经登录
		notifyAllOnlineUsers(userProfile, true)
	}
}

func getRegisterMsgResp(username int, password int) (respMsg protocol.RegisterMsgResp) {
	respMsg = protocol.RegisterMsgResp{}
	ok, err := model.OneUserModel.CheckUserExist(username)

	if ok {
		respMsg.ErrorCode = protocol.UserExist
		respMsg.ErrorMsg = "用户ID被占用，请使用新ID！"
		return
	}

	if err != nil {
		respMsg.ErrorCode = protocol.UnkownError
		respMsg.ErrorMsg = err.Error()
		return
	}

	userProfile := protocol.UserProfile{
		Username: username,
		Password: password,
	}

	err = model.OneUserModel.SetUserInfo(username, userProfile)

	if err != nil {
		respMsg.ErrorCode = protocol.UnkownError
		respMsg.ErrorMsg = err.Error()
	} else {
		respMsg.ErrorCode = protocol.Success
		respMsg.ErrorMsg = "注册成功！"
	}
	return
}

// 处理用户注册请求
func (u *UserProcessor) UserRegisterProcess(username int, password int) {
	respMsg := getRegisterMsgResp(username, password)
	jsonBytes, err := json.Marshal(respMsg)

	if err != nil {
		fmt.Printf("register json.Marshal(respMsg) err, err msg=%v\n", err)
	}
	transfer := utils.Transfer{
		Conn: u.Conn,
	}
	err = transfer.SendMsg(jsonBytes, protocol.RegisterMsgType)

	if err != nil {
		fmt.Printf("transfer.SendMsg(jsonBytes, protocol.RegisterMsgType) err, err msg=%v\n", err)
	}
}

// 处理用户注销
func LogoutProcess(remoteAddr string) {
	username, ok := manager.UserMgr.OnlineUserAddrs[remoteAddr]

	if ok {
		fmt.Printf("此客户端(%s)有用户(%d)登录，群发通知已下线！\n", remoteAddr, username)
		userProfile := protocol.UserProfile{
			Username: username,
		}
		manager.UserMgr.RemoveOnlineUser(userProfile)
		notifyAllOnlineUsers(userProfile, false)
	} else {
		fmt.Printf("此客户端(%s)还未有用户登录，直接退出，不发送通知！\n", remoteAddr)
	}
}
